//
// Created by xkj on 2020/12/18.
//

#ifndef PROJ_ANDROID_LOTTERYRACESCENE_H
#define PROJ_ANDROID_LOTTERYRACESCENE_H


#include <stdlib.h>
#include <strings.h>

#include <map>
#include <string>
#include <atomic>
#include <random>                                // For random_device class

#include <functional>
#include <android/log.h>

#include "base/CCScheduler.h"
#include "base/CCDirector.h"

#include "renderer/CCRenderer.h"
#include "renderer/CCCustomCommand.h"

#include "RemoteControlHelper.h"
#include "../cocos2d/cocos/editor-support/cocostudio/SimpleAudioEngine.h"
#include "BlueToothHelper.h"
#include "SocketIOHelper.h"
#define GAME_UUID_RACE_NDK "GAME_UUID_RACE.plist"

using namespace CocosDenshion;

USING_NS_CC;
USING_NS_CC_EXT;

class  LotterRaceScene: public cocos2d::Scene, public BlueToothHelperDelegate,public SocketIOHelperDelegate {
public:
    static cocos2d::Scene *createScene() {
        return LotterRaceScene::create();
    }

    void initKeyBoard(){
        auto listener = EventListenerKeyboard::create();
        listener->onKeyPressed = [=](EventKeyboard::KeyCode keyCode, Event* event){
            ControlCode pressKey = ControlCode(keyCode);
            setKeyAct(pressKey);
//        auto promptxx = StringUtils::format("按下键盘：%d", static_cast<int>(keyCode));
//        BlueToothHelper::notifyTarget->setNotifyLabel(promptxx);
        };

        listener->onKeyReleased = [=](EventKeyboard::KeyCode keyCode, Event* event){
//        auto promptxx = StringUtils::format("抬起键盘：%d", static_cast<int>(keyCode));
//        BlueToothHelper::notifyTarget->setNotifyLabel(promptxx);
        };

        _eventDispatcher->addEventListenerWithSceneGraphPriority(listener, this);
    }

    void setKeyAct(ControlCode &pressKey) override {

        //如果按返回就退出
        if(pressKey == KEY_RETURN) {
            BlueToothHelper::notifyTarget->setNotifyLabel("ヾ(￣▽￣)Bye~Bye~");
            //Director::getInstance()->end()
            checkoutGlobal();
            auto scene = HelloWorld::createScene();

            Director::getInstance()->replaceScene(TransitionFade::create(2.5, scene, Color3B(58,81,73)));
        }

        if(pressKey == VOLUMN_UP ||
           pressKey == VOLUMN_DOWN
        ) {
            if(pressKey == VOLUMN_UP)
            {

            }

            if(pressKey == VOLUMN_DOWN){

            }

        }

        if(pressKey == PROGRAM_UP ||
           pressKey == PROGRAM_DONW
         ) {
            if(pressKey == PROGRAM_UP) {
            }

            if(pressKey == PROGRAM_DONW) {
            }

        }

        if(pressKey == VOLUMN_MUTE){

        }

    }

    void checkoutGlobal() {
        SocketIOHelper::delegate = static_cast<SocketIOHelperDelegate *>(nullptr);
        BlueToothHelper::notifyTarget = static_cast<BlueToothHelperDelegate *>(nullptr);
    }

    virtual void onEnterTransitionDidFinish() override {
        BlueToothHelper::notifyTarget = static_cast<BlueToothHelperDelegate*>(this);
        SocketIOHelper::delegate =  static_cast<SocketIOHelperDelegate *>(this);

        initBg();//背景
        initTrack();//赛道

        initReadyMask();//遮罩

        initOneRace("xxoo", "user_avator.jpg", "科比扣杰伦");
        initOneRace("xxoo1", "user_avator.jpg","爷酱");
        initOneRace("xxoo2", "user_avator.jpg","今日那蛤");
        initOneRace("xxoo3", "user_avator.jpg","what");

        initStoreUUID();
        initSocketIO();
    }

    void writeGameUUIDInfo()
    {
        std::random_device rd;                         // A function object for generating seeds
        std::string myRand = StringUtils::format("%ud-%ud-%ud",rd(), rd(), rd());
        if(myRand.length() > 32){
            myRand = myRand.substr(0,32);
        }

        ValueMap pageInfo;
        pageInfo["login_sign"] = Value(myRand);

        std::string writablePath = FileUtils::getInstance()->getWritablePath();
        std::string fullPath = writablePath + GAME_UUID_RACE_NDK;
        if (FileUtils::getInstance()->writeValueMapToFile(pageInfo, fullPath.c_str())) {
            ranceUuidInfo = pageInfo;
        } else {
        }
    }

    void initStoreUUID(){
        std::string writablePath = FileUtils::getInstance()->getWritablePath();
        writablePath.append(GAME_UUID_RACE_NDK);
        auto isExist = FileUtils::getInstance()->isFileExist(writablePath);
        if (isExist) {
            ranceUuidInfo = FileUtils::getInstance()->getValueMapFromFile(writablePath);
        } else {
            writeGameUUIDInfo();
        }
    }

    void initSocketIO(bool isForceConn=false){
        float delta = 1.0f+CCRANDOM_0_1();
        this->scheduleOnce([=](float dt) {
            SocketIOHelper::checkConnection(isForceConn);
        },delta ,"initSocketIO");
    };
    void initReadyMask()
    {
        auto blockSize = Size(visibleSize.width , 200);
        float fontSize = 82;

        auto center = Label::createWithTTF("R e a d y", "Abduction.ttf", fontSize,
                                           blockSize, TextHAlignment::CENTER,TextVAlignment::CENTER);

        auto leftColor = LayerColor::create(Color4B(100, 100, 100, 200), blockSize.width/3, visibleSize.height);
        auto centerColor = LayerColor::create(Color4B(200, 100, 100, 200), blockSize.width/3, visibleSize.height);
        auto rightColor = LayerColor::create(Color4B(100, 100, 200, 200), blockSize.width/3, visibleSize.height);

        centerColor->setName("center_ready_mask");

        leftColor->setAnchorPoint(Vec2(0,0));
        leftColor->setPosition(Vec2(0,0));

        centerColor->setAnchorPoint(Vec2(0,0));
        centerColor->setPosition(Vec2(blockSize.width*0.333333,0));

        rightColor->setAnchorPoint(Vec2(0,0));
        rightColor->setPosition(Vec2(blockSize.width*0.6666666,0));


        center->setAnchorPoint(Vec2(0.5, 0));
        center->setPosition(Vec2(centerColor->getContentSize().width*0.5,centerColor->getContentSize().height*0.64));
        centerColor->addChild(center);

        this->addChild(leftColor);
        this->addChild(centerColor);
        this->addChild(rightColor);
    }

    void initOneRace(std::string wxName, std::string facePath, std::string name)
    {
        int headNum = cocos2d::random(1,9);
        std::string carName = "car";
        carName.append(std::to_string(headNum)).append(".png");

        curTrackNum++;
        if(curTrackNum>4){
            curTrackNum = 1;
        }
        std::string trackName = "track_";
        trackName.append(std::to_string(curTrackNum));

        float posY = cocos2d::random((float)0.0, (float)(oneTrackHeight-oneCarScale*visibleSize.height));        //oneCarScale一辆车の尺寸

        //车
        auto spriteB1 = Sprite::create(carName);
        spriteB1->setScale(oneCarScale*visibleSize.height/spriteB1->getContentSize().height);
        spriteB1->setAnchorPoint(Vec2(0, 0));//左下角
        spriteB1->setPosition(Vec2(0, 0));
        spriteB1->setName("car");

        //微信头像
        auto spriteB2 = Sprite::create(facePath);
        spriteB2->setScale(spriteB1->getBoundingBox().size.height/spriteB2->getBoundingBox().size.height);
        spriteB2->setPosition(Vec2(-5, 0));//左下角
        spriteB2->setAnchorPoint(Vec2(1, 0));

        //名砸
        float posB3X = -1*(spriteB2->getBoundingBox().size.width+10);
        float posB3Y = spriteB2->getBoundingBox().size.height/2;
        auto spriteB3 =  Label::createWithTTF(name, "fonts/content.ttf",  36);
        spriteB3->setAnchorPoint(Vec2(1,0.5));
        spriteB3->setPosition(Vec2(posB3X, posB3Y));

        auto colorLayer = LayerColor::create(Color4B(255,25,150,100), spriteB1->getBoundingBox().size.width, spriteB1->getBoundingBox().size.height);
        colorLayer->setAnchorPoint(Vec2(1,0));
        colorLayer->setName(wxName);
        colorLayer->setPosition(Vec2(beginY, posY));
        colorLayer->addChild(spriteB1);
        colorLayer->addChild(spriteB2);
        colorLayer->addChild(spriteB3);

        this->getChildByName(trackName)->addChild(colorLayer);

        carMapping[wxName] = colorLayer;
    }

    void initTrack()
    {
        curTrackNum = 0;

        //0.145 第一条赛道
        createTrack(trackPadding[0],"track_3");

        //0.327 第二条赛道
        createTrack(trackPadding[1],"track_1");

        //0.542 第三条赛道
        createTrack(trackPadding[2],"track_2");

        //0.759 第四条赛道
        createTrack(trackPadding[3],"track_4");

        finishY = visibleSize.width * finishPoint;
        beginY = 0.1083 * visibleSize.width;
        oneTrackStep = (finishY -  beginY) / (60*10);//10秒钟

        scheduleUpdate();
    }

    virtual void update(float time) override
    {
        if(!isBeginRace){
            return;
        }

        for(const auto &oneMapping :carMapping) {
            if ((oneMapping.second->getPositionX()+oneMapping.second->getContentSize().width) > finishY) {
                continue;
            }

            //unscheduleUpdate();
            oneMapping.second->setPositionX(oneMapping.second->getPositionX() + oneTrackStep);

            LOGD("update(%s):%f -> %f", oneMapping.first.c_str(), oneMapping.second->getPositionX(), finishY);
        }
    }

    void createTrack(float heightPosVec, const char *name)
    {
        //0.175 一条赛道
        oneTrackHeight = visibleSize.height*0.175;
        float heightPos = visibleSize.height*heightPosVec;

        auto colorLayer = LayerColor::create(Color4B(150,25,150,125), visibleSize.width, oneTrackHeight);
        colorLayer->setAnchorPoint(Vec2(1,0));
        colorLayer->setName(name);
        colorLayer->setPosition(Vec2(0,heightPos));
        this->addChild(colorLayer);
    }

    void initBg()
    {
        auto bg = Sprite::create("race_road.jpg");//, Rect(0, 0, visibleSize.width, visibleSize.height));
        Size mysize = bg->getContentSize();
        bg->setScaleX(visibleSize.width/mysize.width);
        bg->setScaleY(visibleSize.height/mysize.height);

        //贴图的纹理参数，水平重复平铺，垂直重复平铺
        /*
        Texture2D::TexParams tp = {                backend::SamplerFilter::LINEAR,
                                                   backend::SamplerFilter::LINEAR,
                                                   backend::SamplerAddressMode::REPEAT,
                                                   backend::SamplerAddressMode::REPEAT
        };
        //bg->getTexture()->setTexParameters(tp);
         */
        bg->setAnchorPoint(Vec2::ZERO);
        bg->setPosition(0,0);//origin + Vec2(visibleSize.width/2, visibleSize.height/2));
        this->addChild(bg, -1);


    }

    virtual void setNotifyLabel(std::string cnt) override
    {
        if(displayLabel != nullptr) {
            displayLabel->setString(cnt);
        }
    }

    virtual bool init() override {
        visibleSize = Director::getInstance()->getVisibleSize();

        initKeyBoard();

        return true;
    }

    //放下一个命令
    virtual void setOneAct(ActCmd &oneCmd) override
    {

    }
    virtual void SioRoomVisitors(SIOClient *client, const std::string& msg) override {
    }
    virtual void SioConnection(SIOClient *client, const std::string& msg) override {
        SioJoinRoom();
    }
    void SioJoinRoom(){
        std::string channelName = "lottery_race";

        channelName.append(StringUtils::format("_",ranceUuidInfo["login_sign"].asString().c_str()));
        if(channelName == SIOjoinRoom){
            return;
        }

        SIOjoinRoom = channelName;

        SocketIOHelper::getInstant()->emit("store-roomid", channelName);

        channelName.append("\r\nND_PAD\r\navatorOTT\r\n智慧好字帖赛车抽奖\r\n1\r\nsignatureOTT\r\n ");

        SocketIOHelper::getInstant()->emit("join-room", channelName);
    };
    virtual void SioOnline(SIOClient *client, const std::string& msg) override {

    }
    virtual void SioStatInfo(SIOClient *client, const std::string& msg) override {
        isBeginRace = true;


    }
    virtual void SioStoreRoomid(SIOClient *client, const std::string& msg) override {
    }
    virtual void SioShareCode(SIOClient *client, const std::string& msg) override {

    }
    virtual void SioOffline(SIOClient *client, const std::string& msg) override {
    }
    virtual void SioTalking(SIOClient *client, const std::string& msg) override {
    }
    virtual  void SioRoomCommentator(SIOClient *client, const std::string& msg) override {
    }
    virtual void SioOnConnect(SIOClient *client) override {
    }
    virtual void SioOnMessage(SIOClient *client, const std::string& msg) override {
    }
    virtual void SioOnError(SIOClient *client, const std::string& msg) override {
        initSocketIO(true);
    }
    virtual void SioOnClose(SIOClient *client) override {
        initSocketIO(true);
    }

    CREATE_FUNC(LotterRaceScene);

private:
    cocos2d::Size visibleSize;
    cocos2d::Label*  displayLabel;
    float oneTrackHeight;
    int curTrackNum;
    const std::array<float,4> trackPadding = {0.145,0.34,0.55,0.759};
    const float oneCarScale = 0.06;
    const float finishPoint = 0.964;
    float finishY;
    float beginY;
    float oneTrackStep;
    std::map<std::string,LayerColor*> carMapping;
    bool isBeginRace = false;
    ValueMap ranceUuidInfo;
    std::string SIOjoinRoom;

};

#endif //PROJ_ANDROID_LOTTERYRACESCENE_H
